-- LuaTools需要PROJECT和VERSION这两个信息
PROJECT = "esp32c3-wifidemo"
VERSION = "1.0.0"

-- 引入必要的库文件(lua编写), 内部库不需要require
sys = require("sys")
require("sysplus")



-- 兼容V1001固件的
if http == nil and http2 then
    http = http2
end
--获取随机颜色
function radom_color()
    local color = "0x"
    for i=1,6 do
        color = color .. string.format("%x",math.random(0,15))
    end
    return color

end

local ws2812_w = 1
local ws2812_h = 1


local mqtt_host = "iot.isuoge.com"
local mqtt_port = 1883
local mqtt_isssl = false
local client_id = "esp32-c3-002" -- mcu.unique_id()
local user_name = "esp32-c3-002"
local password = "password"
local mqttc = nil

-- gpio定义
local netLedPin = 13 --网络灯

local pinData = {
    fishLight = {
        pin = 2,--定义引脚
        actionTime = 0, --触发的时间，用来记录上次启动时间 方便计算运行时长
        cdTime = 30, -- 关闭触发间隔时间(单位:秒)，防止设备长时间运行
        value = 0, -- 引脚电平
        pinType = "gpio" -- 引脚触发类型  gpio 0 1  pwm 0-100
    }
}


-- gpio引脚初始化
gpio.setup(netLedPin, 0)
gpio.setup(pinData.fishLight.pin,0, gpio.PULLDOWN,gpio.BOTH)
-- 网络状态
local netStatus = false

-- 测试led 已作废
function testLed()
    while true do
        sys.wait(1000)
        local rgb = radom_color()
        local color = tonumber(rgb,16)
        local buff = zbuff.create({ws2812_w,ws2812_h,24},color)
        log.info(PROJECT, "test running...")


        -- buff:setFrameBuffer(ws2812_w,ws2812_h,24,tonumber(rgb,16))
        log.info(PROJECT, color)
        -- 在任务函数中使用wait进行1S延时
        -- buff:pixel(0,0,tonumber(rgb,16))
        sensor.ws2812b(3,buff,0,10,10,0)

    end
    -- pwm控制
    -- while true do
    --     for i=0, 100 do
    --         pwm.open(13, 10000, i)
    --         print(i)
    --         sys.wait(100)
    --     end
    --     for i=99,0, -1 do
    --         pwm.open(13, 10000, i)
    --         print(i)
    --         sys.wait(100)
    --     end

    -- end

    -- gpio控制
    -- local gpioPin = 7
    -- gpio.setup(gpioPin, 0)
    -- gpio.set(gpioPin,1)
    -- local count = 0
    -- while true do
    --     count = count+1
    --     if count%2 == 1 then
    --         gpio.set(gpioPin,1)
    --     else
    --         gpio.set(gpioPin,0)
    --     end
    --     print(count)
    --     sys.wait(1000)
    -- end

end


-- 网络灯闪烁
function netLedShine()
    local isLight = false
    while true do
        if isLight then
            gpio.set(netLedPin,0)
        else
            gpio.set(netLedPin,1)
        end
        isLight = not isLight
        if netStatus then
            sys.wait(3000)
        else
            sys.wait(500)
        end

    end
end

--IO操作
function ioHandle(pinName,value)
    for key, item in pairs(pinData) do
        if key == pinName then
            gpio.set(pinData[pinName].pin,value)
            pinData[pinName].value = value
            print('pinName',pinName,pinData[pinName].value)
        end
    end
end


sys.taskInit(function()
    sys.wait(1000)

    wlan.init()
    wlan.connect("cats", "18725741170")
    log.info("wlan", "wait for IP_READY")
    sys.waitUntil("IP_READY", 30000)
    if wlan.ready() then
        log.info("wlan", "ready !!")
        sys.wait(100)
        local url = "http://ip.nutz.cn/json"
        -- local url = "http://nutzam.com/1.txt"
        local code, headers, body = http.request("GET", url).wait()
        log.info("http", code, json.encode(headers or {}), body and #body or 0)

        -- 网络状态
        netStatus = true
        sys.subscribe("IP_READY", function(adapter)
            netStatus = true
            log.info("网络连接", "IP_READY")
        end)
        sys.subscribe("IP_LOSE", function(adapter)
            netStatus = false
            log.info("网络丢失", "IP_LOSE")
        end)

        --mqtt连接
        mqttc = mqtt.create(nil,mqtt_host, mqtt_port, mqtt_isssl, ca_file)

        mqttc:auth(client_id,user_name,password) -- client_id必填,其余选填
        mqttc:keepalive(30) -- 默认值240s
        mqttc:autoreconn(true, 3000) -- 自动重连机制

        mqttc:on(function(mqtt_client, event, data, payload)
            -- 用户自定义代码
            log.info("mqtt", "event", event, mqtt_client, data, payload)
            if event == "conack" then
                sys.publish("mqtt_conack")
                mqtt_client:subscribe("/iot/smartgarden/"..user_name.."/io_controller")
            elseif event == "recv" then
                log.info("mqtt", "downlink", "topic", data, "payload", payload,os.time(),os.date)
                local t = rtc.get()
                log.info("rtc", json.encode(t))
                -- gpio.set(22, 1)--引脚高电平
                local payloadData =  json.decode(payload)
                if payloadData.type == "ioHandle" then
                    --IO操作
                    ioHandle(payloadData.data.name,payloadData.data.value)
                    if  payloadData.data.value>0 then--记录开始时间
                        pinData[payloadData.data.name].actionTime = os.time()
                    end
                end
            elseif event == "sent" then
                log.info("mqtt", "sent", "pkgid", data)
            -- elseif event == "disconnect" then
                -- 非自动重连时,按需重启mqttc
                -- mqtt_client:connect()
            end
        end)

        mqttc:connect()
        sys.waitUntil("mqtt_conack")
        while true do
            -- mqttc自动处理重连
            local ret, topic, data, qos = sys.waitUntil("mqtt_pub", 30000)
            if ret then
                if topic == "close" then break end
                mqttc:publish(topic, data, qos)
            end
        end
        mqttc:close()
        mqttc = nil






    else
        print("wlan NOT ready!!!!")
    end

end)

--网络状态灯，单独开协程处理是避免sys.wait()对其他逻辑的阻塞
sys.taskInit(function ()
    netLedShine()
end)



--添加硬狗防止程序卡死
if wdt then
    wdt.init(9000)--初始化watchdog设置为9s
    sys.timerLoopStart(wdt.feed, 3000)--3s喂一次狗
end

--mqtt事件处理
sys.taskInit(function()
	local topic = "/iot/smartgarden/"..user_name.."/io_status"
	-- local data = "123"
	-- local qos = 1
    while true do
        -- 5秒发送一次IO状态数据
        sys.wait(5000)
        if mqttc and mqttc:ready() then
            --读取引脚数据
            local data = {}
            for key, item in pairs(pinData) do
                data[key] = pinData[key].value
            end
            --发布数据
            jsondata = json.encode({type="ioStatus",data=data})
            local pkgid = mqttc:publish(topic, jsondata, 1)

        end
    end
end)

local commandMsg = {
    "verandaLight",
    "verandaLight",
    "topLight",
    {
        "verandaLight",
        "topLight",
    },
    "verandaLight",
    "verandaLight",
    "topLight",
    {
        "verandaLight",
        "topLight",
    },
}


--根据串口反馈接收到的语音命令ID发送MQtt消息控制IO
function setLightByMqtt(commandid)

    commandid = tonumber(commandid)
    ioName = commandMsg[commandid]
    if type(ioName)=='table' then
        for key, item in pairs(ioName) do
            -- log.info("arrData: ", key, item)
            sendByName(item,commandid)
        end

    else
        sendByName(ioName,commandid)
    end

end

function sendByName(ioName,id)
    local topic = "/iot/smartgarden/io_controller"
    if mqttc and mqttc:ready() then
        local data = {name = ioName,}
        if id>4 then
            data["value"] = 0
        else
            data["value"] = 1
        end
        jsondata = json.encode({type="ioHandle",data=data})
        -- log.info("send Data: ", jsondata)
        local pkgid = mqttc:publish(topic, jsondata, 1)
    end
end

--处理IO运行超时
sys.taskInit(function()
    while true do
        sys.wait(1000)
        --工作超时保护，防止设备运行超时（比如浇水水泵）  配置cdTime大于0时生效 为0则可以不间断运行（比如过滤泵）
        for key, item in pairs(pinData) do
            if pinData[key].cdTime >0 and pinData[key].value>0 and  os.time() - pinData[key].actionTime > pinData[key].cdTime then
                ioHandle(key,0)
                print('触发超时保护',key,pinData[key].value)
            end
        end

    end
end)


--初始化串口信息
uart.setup(1, 115200, 8, 1, uart.NONE)
--处理串口信息
sys.taskInit(function ()
    uart.on(1,"receive",function (id,len)
        local data = uart.read(id, len)
        log.info("uart--receive: ", id, len, data)
        setLightByMqtt(data)
    end)
end)

-- 用户代码已结束---------------------------------------------
-- 结尾总是这一句
sys.run()
-- sys.run()之后后面不要加任何语句!!!!!
